/**     
 * @Title: RequestDispatcherHandler.java   
 * @Package me.springboot.netty.handler   
 * @Description: TODO
 * @author weiwei 
 * @date 2017年8月25日 下午2:40:15   
 * @version V1.0     
 */
package me.springboot.netty.handler;

import io.netty.channel.ChannelHandler.Sharable;
import static com.google.common.base.Preconditions.checkNotNull;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import javax.servlet.http.HttpServletResponse;

import me.springboot.netty.context.NettyEmbeddedContext;
import me.springboot.netty.dispatcher.NettyRequestDispatcher;
import me.springboot.netty.servlet.NettyHttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @ClassName: RequestDispatcherHandler
 * @Description: TODO
 * @author weiwei
 * @date 2017年8月25日 下午2:40:15
 * 
 */
@Sharable
public class RequestDispatcherHandler extends SimpleChannelInboundHandler<NettyHttpServletRequest> {

	private final Log logger = LogFactory.getLog(getClass());

	private final NettyEmbeddedContext context;

	public RequestDispatcherHandler(NettyEmbeddedContext context) {
		this.context = checkNotNull(context);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, NettyHttpServletRequest request) throws Exception {
		HttpServletResponse servletResponse = (HttpServletResponse) request.getServletResponse();
		try {
			NettyRequestDispatcher dispatcher = (NettyRequestDispatcher) context.getRequestDispatcher(request.getRequestURI());
			if (dispatcher == null) {
				servletResponse.sendError(404);
				return;
			}
			dispatcher.dispatch(request, servletResponse);
		} finally {
			if (!request.isAsyncStarted()) {
				servletResponse.getOutputStream().close();
			}
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		logger.error("Unexpected exception caught during request", cause);
		ctx.close();
	}

}
